package com.aims.server.service.impl;

import com.aims.server.dao.mapper.FlowAccountInfoMapper;
import com.aims.server.dao.mapper.FlowAccountProcessInfoMapper;
import com.aims.server.dao.mapper.ProProductMapper;
import com.aims.server.domain.dto.AccountWorkbenchQueryDTO;
import com.aims.server.domain.vo.*;
import com.aims.server.entity.FlowAccountInfo;
import com.aims.server.entity.FlowAccountProcessInfo;
import com.aims.server.entity.ProProduct;
import com.aims.server.service.AccountWorkbenchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 账户办理工作台Service实现
 */
@Service
public class AccountWorkbenchServiceImpl implements AccountWorkbenchService {

    @Autowired
    private FlowAccountInfoMapper accountInfoMapper;

    @Autowired
    private FlowAccountProcessInfoMapper processInfoMapper;

    @Autowired
    private ProProductMapper productMapper;

    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public AccountCalendarVO getCalendarView(AccountWorkbenchQueryDTO query) {
        AccountCalendarVO calendarVO = new AccountCalendarVO();
        calendarVO.setStartDate(query.getStartDate());
        calendarVO.setEndDate(query.getEndDate());

        // 查询任务列表
        List<AccountTaskVO> taskList = getTaskList(query);

        // 按日期分组
        Map<String, List<AccountTaskVO>> tasksByDate = taskList.stream()
                .collect(Collectors.groupingBy(task -> {
                    if (task.getExpectedFinishDate() != null) {
                        return task.getExpectedFinishDate();
                    }
                    return task.getCreatedDate().format(DATE_FORMATTER);
                }));

        calendarVO.setTasksByDate(tasksByDate);

        // 按环节分组
        Map<String, List<AccountTaskVO>> tasksByStage = taskList.stream()
                .collect(Collectors.groupingBy(task ->
                        task.getCurrentStage() != null ? task.getCurrentStage() : "未分类"));

        calendarVO.setTasksByStage(tasksByStage);

        // 统计数据
        TaskStatisticsVO statistics = getTaskStatistics(query);
        calendarVO.setStatistics(statistics);

        return calendarVO;
    }

    @Override
    public List<AccountTaskVO> getTaskList(AccountWorkbenchQueryDTO query) {
        List<AccountTaskVO> taskList = new ArrayList<>();

        // 查询账户信息
        List<FlowAccountInfo> accountInfoList = accountInfoMapper.selectList(query);

        for (FlowAccountInfo accountInfo : accountInfoList) {
            // 查询流程信息
            FlowAccountProcessInfo processInfo = processInfoMapper.selectByProcessInstanceId(
                    accountInfo.getProcessInstanceId());

            if (processInfo != null) {
                // 根据查询条件过滤
                if (query.getBusinessType() != null &&
                        !query.getBusinessType().equals(processInfo.getBusinessType())) {
                    continue;
                }
                if (query.getProgressCode() != null && !query.getProgressCode().isEmpty() &&
                        !query.getProgressCode().equals(processInfo.getProgressCode())) {
                    continue;
                }

                AccountTaskVO taskVO = buildAccountTaskVO(accountInfo, processInfo);
                taskList.add(taskVO);
            }
        }

        return taskList;
    }

    @Override
    public AccountTaskVO getTaskDetail(Long processInstanceId) {
        FlowAccountInfo accountInfo = accountInfoMapper.selectByProcessInstanceId(processInstanceId);
        if (accountInfo == null) {
            return null;
        }

        FlowAccountProcessInfo processInfo = processInfoMapper.selectByProcessInstanceId(processInstanceId);
        if (processInfo == null) {
            return null;
        }

        AccountTaskVO taskVO = buildAccountTaskVO(accountInfo, processInfo);

        // 构建子任务列表(示例数据,实际应从数据库查询)
        List<SubTaskVO> subTasks = buildSubTasks(accountInfo, processInfo);
        taskVO.setSubTasks(subTasks);

        // 构建委托信息
        DelegationInfoVO delegationInfo = new DelegationInfoVO();
        delegationInfo.setPrincipal(accountInfo.getCreatedBy());
        delegationInfo.setAgent(accountInfo.getAgentBy());
        taskVO.setDelegationInfo(delegationInfo);

        // 构建辅助信息
        AuxiliaryInfoVO auxiliaryInfo = new AuxiliaryInfoVO();
        if (accountInfo.getProductId() != null) {
            ProProduct product = productMapper.selectById(accountInfo.getProductId());
            if (product != null) {
                auxiliaryInfo.setProductName(product.getProductName());
            }
        }
        taskVO.setAuxiliaryInfo(auxiliaryInfo);

        return taskVO;
    }

    @Override
    public TaskStatisticsVO getTaskStatistics(AccountWorkbenchQueryDTO query) {
        TaskStatisticsVO statistics = new TaskStatisticsVO();

        // 全部任务
        int totalCount = accountInfoMapper.count(query);
        statistics.setTotalTasks(totalCount);

        // 按业务类型统计
        AccountWorkbenchQueryDTO openQuery = new AccountWorkbenchQueryDTO();
        copyQueryFields(query, openQuery);
        openQuery.setBusinessType(1); // 开户
        List<FlowAccountInfo> openList = accountInfoMapper.selectList(openQuery);
        int openCount = 0;
        for (FlowAccountInfo info : openList) {
            FlowAccountProcessInfo processInfo = processInfoMapper.selectByProcessInstanceId(info.getProcessInstanceId());
            if (processInfo != null && processInfo.getBusinessType() != null && processInfo.getBusinessType() == 1) {
                openCount++;
            }
        }
        statistics.setOpenAccountTasks(openCount);

        // 销户
        AccountWorkbenchQueryDTO closeQuery = new AccountWorkbenchQueryDTO();
        copyQueryFields(query, closeQuery);
        closeQuery.setBusinessType(3);
        List<FlowAccountInfo> closeList = accountInfoMapper.selectList(closeQuery);
        int closeCount = 0;
        for (FlowAccountInfo info : closeList) {
            FlowAccountProcessInfo processInfo = processInfoMapper.selectByProcessInstanceId(info.getProcessInstanceId());
            if (processInfo != null && processInfo.getBusinessType() != null && processInfo.getBusinessType() == 3) {
                closeCount++;
            }
        }
        statistics.setCloseAccountTasks(closeCount);

        // 变更
        AccountWorkbenchQueryDTO changeQuery = new AccountWorkbenchQueryDTO();
        copyQueryFields(query, changeQuery);
        changeQuery.setBusinessType(2);
        List<FlowAccountInfo> changeList = accountInfoMapper.selectList(changeQuery);
        int changeCount = 0;
        for (FlowAccountInfo info : changeList) {
            FlowAccountProcessInfo processInfo = processInfoMapper.selectByProcessInstanceId(info.getProcessInstanceId());
            if (processInfo != null && processInfo.getBusinessType() != null && processInfo.getBusinessType() == 2) {
                changeCount++;
            }
        }
        statistics.setChangeTasks(changeCount);

        // 按环节统计(示例,实际应根据progress_code统计)
        statistics.setMaterialPreparationTasks(0);
        statistics.setSubmitSealTasks(0);
        statistics.setSubmitInstitutionTasks(0);
        statistics.setReceiptReportTasks(0);

        return statistics;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTaskProgress(Long processInstanceId, String progressCode, String remark) {
        FlowAccountProcessInfo processInfo = processInfoMapper.selectByProcessInstanceId(processInstanceId);
        if (processInfo != null) {
            processInfo.setProgressCode(progressCode);
            processInfo.setProgressRemark(remark);
            processInfoMapper.updateById(processInfo);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markTaskUrgent(Long processInstanceId, Integer isUrgent) {
        FlowAccountInfo accountInfo = accountInfoMapper.selectByProcessInstanceId(processInstanceId);
        if (accountInfo != null) {
            accountInfo.setIsUrgent(isUrgent);
            accountInfoMapper.updateById(accountInfo);
        }
    }

    /**
     * 构建AccountTaskVO
     */
    private AccountTaskVO buildAccountTaskVO(FlowAccountInfo accountInfo, FlowAccountProcessInfo processInfo) {
        AccountTaskVO taskVO = new AccountTaskVO();
        taskVO.setTaskId(accountInfo.getProcessInstanceId());
        taskVO.setAccountId(accountInfo.getId());

        // 任务名称
        String taskName = "";
        if (accountInfo.getAcctInstitution() != null) {
            taskName = accountInfo.getAcctInstitution();
        }
        if (accountInfo.getAcctName() != null) {
            taskName += "-" + accountInfo.getAcctName();
        }
        taskVO.setTaskName(taskName);

        // 业务类型
        if (processInfo.getBusinessType() != null) {
            taskVO.setBusinessType(processInfo.getBusinessType());
            taskVO.setBusinessTypeName(getBusinessTypeName(processInfo.getBusinessType()));
        }

        // 当前环节
        taskVO.setCurrentStage(processInfo.getProgressCode());
        taskVO.setCurrentStageName(getProgressName(processInfo.getProgressCode()));

        // 其他字段
        taskVO.setExpectedFinishDate(accountInfo.getExpectedFinishDate());
        taskVO.setIsUrgent(accountInfo.getIsUrgent());
        taskVO.setIsUrgentName(accountInfo.getIsUrgent() != null && accountInfo.getIsUrgent() == 1 ? "是" : "否");
        taskVO.setCreatedDate(accountInfo.getCreatedDate());
        taskVO.setProductId(accountInfo.getProductId());
        taskVO.setAgent(accountInfo.getAgentBy());
        taskVO.setInstitution(accountInfo.getAcctInstitution());

        // 查询产品名称
        if (accountInfo.getProductId() != null) {
            ProProduct product = productMapper.selectById(accountInfo.getProductId());
            if (product != null) {
                taskVO.setProductName(product.getProductName());
            }
        }

        // 计算进度(示例)
        taskVO.setTaskProgress(calculateProgress(processInfo.getProgressCode()));

        return taskVO;
    }

    /**
     * 构建子任务列表
     */
    private List<SubTaskVO> buildSubTasks(FlowAccountInfo accountInfo, FlowAccountProcessInfo processInfo) {
        List<SubTaskVO> subTasks = new ArrayList<>();

        // 示例子任务
        SubTaskVO subTask1 = new SubTaskVO();
        subTask1.setId(1L);
        subTask1.setTaskName("准备客户身份证明");
        subTask1.setStatus(1);
        subTask1.setStatusName("已完成");
        subTask1.setSortOrder(1);
        subTasks.add(subTask1);

        SubTaskVO subTask2 = new SubTaskVO();
        subTask2.setId(2L);
        subTask2.setTaskName("准备风险测评报告");
        subTask2.setStatus(0);
        subTask2.setStatusName("去准备");
        subTask2.setSortOrder(2);
        subTasks.add(subTask2);

        SubTaskVO subTask3 = new SubTaskVO();
        subTask3.setId(3L);
        subTask3.setTaskName("填写产品申请表");
        subTask3.setStatus(0);
        subTask3.setStatusName("去填写");
        subTask3.setSortOrder(3);
        subTasks.add(subTask3);

        return subTasks;
    }

    /**
     * 获取业务类型名称
     */
    private String getBusinessTypeName(Integer businessType) {
        if (businessType == null) {
            return "";
        }
        switch (businessType) {
            case 1:
                return "开户";
            case 2:
                return "变更";
            case 3:
                return "销户";
            default:
                return "";
        }
    }

    /**
     * 获取进度名称
     */
    private String getProgressName(String progressCode) {
        if (progressCode == null || progressCode.isEmpty()) {
            return "资料准备";
        }
        // 根据需求文档：
        // 资料准备: progress_code=资料准备中
        // 提交用印: progress_code=资料用印中
        // 递交机构: node_code=递交机构
        // 账户报备: node_code=账户报备
        switch (progressCode) {
            case "资料准备中":
                return "资料准备";
            case "资料用印中":
                return "提交用印";
            case "递交机构":
                return "递交机构";
            case "账户报备":
                return "账户回执报备";
            case "1":
                return "资料准备";
            case "2":
                return "提交用印";
            case "3":
                return "递交机构";
            case "4":
                return "账户回执报备";
            default:
                return "资料准备";
        }
    }

    /**
     * 计算进度
     */
    private Integer calculateProgress(String progressCode) {
        if (progressCode == null || progressCode.isEmpty()) {
            return 25;
        }
        switch (progressCode) {
            case "1":
                return 25;
            case "2":
                return 50;
            case "3":
                return 75;
            case "4":
                return 100;
            default:
                return 25;
        }
    }

    /**
     * 复制查询条件
     */
    private void copyQueryFields(AccountWorkbenchQueryDTO source, AccountWorkbenchQueryDTO target) {
        target.setStartDate(source.getStartDate());
        target.setEndDate(source.getEndDate());
        target.setIsUrgent(source.getIsUrgent());
        target.setProductId(source.getProductId());
        target.setAcctInstitution(source.getAcctInstitution());
        target.setStatus(source.getStatus());
        target.setAgentBy(source.getAgentBy());
        target.setCurrentUser(source.getCurrentUser());
        target.setProgressCode(source.getProgressCode());
    }

    @Override
    public WorkbenchDataVO getWorkbenchData(AccountWorkbenchQueryDTO query) {
        WorkbenchDataVO workbenchData = new WorkbenchDataVO();

        // 获取统计数据
        TaskStatisticsVO statistics = getTaskStatistics(query);
        workbenchData.setStatistics(statistics);

        // 获取四个泳道数据
        List<LaneDataVO> lanes = buildLanes(query);
        workbenchData.setLanes(lanes);

        // 获取日历计数
        if (query.getStartDate() != null && query.getEndDate() != null) {
            Map<String, Integer> calendarCounts = getCalendarCounts(query.getStartDate(), query.getEndDate());
            workbenchData.setCalendarCounts(calendarCounts);
        }

        return workbenchData;
    }

    @Override
    public Map<String, Integer> getCalendarCounts(String startDate, String endDate) {
        Map<String, Integer> counts = new HashMap<>();

        AccountWorkbenchQueryDTO query = new AccountWorkbenchQueryDTO();
        query.setStartDate(startDate);
        query.setEndDate(endDate);

        List<AccountTaskVO> tasks = getTaskList(query);

        // 按日期统计
        for (AccountTaskVO task : tasks) {
            String date = task.getExpectedFinishDate();
            if (date != null) {
                counts.put(date, counts.getOrDefault(date, 0) + 1);
            }
        }

        return counts;
    }

    @Override
    public AccountCardVO getCardDetail(String cardId) {
        // 简化实现：从cardId中解析出查询条件
        // 实际应该维护cardId到processInstanceIds的映射
        return new AccountCardVO();
    }

    /**
     * 构建四个泳道数据
     */
    private List<LaneDataVO> buildLanes(AccountWorkbenchQueryDTO query) {
        List<LaneDataVO> lanes = new ArrayList<>();

        // 泳道1：资料准备
        lanes.add(buildLaneData("1", "资料准备", query));

        // 泳道2：提交用印
        lanes.add(buildLaneData("2", "提交用印", query));

        // 泳道3：递交机构
        lanes.add(buildLaneData("3", "递交机构", query));

        // 泳道4：账户回执报备
        lanes.add(buildLaneData("4", "账户回执报备", query));

        return lanes;
    }

    /**
     * 构建单个泳道数据
     */
    private LaneDataVO buildLaneData(String progressCode, String laneName, AccountWorkbenchQueryDTO query) {
        LaneDataVO lane = new LaneDataVO();
        lane.setLaneCode(progressCode);
        lane.setLaneName(laneName);

        // 创建新查询条件
        AccountWorkbenchQueryDTO laneQuery = new AccountWorkbenchQueryDTO();
        copyQueryFields(query, laneQuery);
        laneQuery.setProgressCode(progressCode);

        // 查询该泳道的所有任务
        List<FlowAccountInfo> accountInfoList = accountInfoMapper.selectList(laneQuery);

        // 按合并键分组
        Map<String, AccountCardVO> cardMap = new HashMap<>();

        for (FlowAccountInfo accountInfo : accountInfoList) {
            FlowAccountProcessInfo processInfo = processInfoMapper.selectByProcessInstanceId(
                    accountInfo.getProcessInstanceId());

            if (processInfo != null && progressCode.equals(processInfo.getProgressCode())) {
                // 构建合并键
                String mergeKey = buildMergeKey(accountInfo, processInfo);

                AccountCardVO card = cardMap.get(mergeKey);
                if (card == null) {
                    card = buildAccountCard(accountInfo, processInfo);
                    card.setCardId(mergeKey);
                    card.setAcctCount(1);
                    card.setProcessInstanceIds(new ArrayList<>());
                    cardMap.put(mergeKey, card);
                } else {
                    card.setAcctCount(card.getAcctCount() + 1);
                }
                card.getProcessInstanceIds().add(accountInfo.getProcessInstanceId());
            }
        }

        List<AccountCardVO> cards = new ArrayList<>(cardMap.values());
        lane.setCards(cards);
        lane.setCount(cards.size());

        return lane;
    }

    /**
     * 构建卡片合并键
     * 合并规则：账户类型+子账户类型+业务类型+开户机构+期望完成日期
     */
    private String buildMergeKey(FlowAccountInfo accountInfo, FlowAccountProcessInfo processInfo) {
        StringBuilder key = new StringBuilder();
        key.append(accountInfo.getAcctType() != null ? accountInfo.getAcctType() : "");
        key.append("_");
        key.append(accountInfo.getSubAcctType() != null ? accountInfo.getSubAcctType() : "");
        key.append("_");
        key.append(processInfo.getBusinessType() != null ? processInfo.getBusinessType() : "");
        key.append("_");
        key.append(accountInfo.getAcctInstitution() != null ? accountInfo.getAcctInstitution() : "");
        key.append("_");
        key.append(accountInfo.getExpectedFinishDate() != null ? accountInfo.getExpectedFinishDate() : "");
        return key.toString().hashCode() + "";
    }

    /**
     * 构建账户卡片VO
     */
    private AccountCardVO buildAccountCard(FlowAccountInfo accountInfo, FlowAccountProcessInfo processInfo) {
        AccountCardVO card = new AccountCardVO();

        // 卡片标题：<开户机构简称>-<账户类型>
        String title = (accountInfo.getAcctInstitution() != null ? accountInfo.getAcctInstitution() : "") +
                       "-" + getAcctTypeName(String.valueOf(accountInfo.getAcctType()));
        card.setTitle(title);

        // 基本信息
        card.setBusinessType(processInfo.getBusinessType());
        card.setBusinessTypeName(getBusinessTypeName(processInfo.getBusinessType()));
        card.setAcctType(String.valueOf(accountInfo.getAcctType()));
        card.setSubAcctType(String.valueOf(accountInfo.getSubAcctType()));
        card.setAcctOpenBank(accountInfo.getAcctInstitution());
        card.setAcctOpenBankShort(accountInfo.getAcctInstitution()); // TODO: 从机构表查询简称
        card.setExpectedDate(accountInfo.getExpectedFinishDate());
        card.setIsUrgent(accountInfo.getIsUrgent());

        // 进度信息
        card.setCurrentNode(getProgressName(processInfo.getProgressCode()));
        card.setProgressCode(processInfo.getProgressCode());
        card.setProgressName(getProgressName(processInfo.getProgressCode()));
        card.setStatusText(getStatusText(processInfo.getProgressCode(), processInfo.getStatus()));

        // 构建子任务
        List<SubTaskVO> subTasks = buildSubTasksForCard(accountInfo, processInfo);
        card.setSubTasks(subTasks);

        return card;
    }

    /**
     * 为卡片构建子任务列表
     */
    private List<SubTaskVO> buildSubTasksForCard(FlowAccountInfo accountInfo, FlowAccountProcessInfo processInfo) {
        List<SubTaskVO> subTasks = new ArrayList<>();

        String progressCode = processInfo.getProgressCode();

        // 根据不同环节生成不同的子任务
        if ("1".equals(progressCode)) {
            // 资料准备阶段
            subTasks.add(createSubTask("准备客户身份证明", 1, "已完成"));
            subTasks.add(createSubTask("准备风险测评报告", 2, "去准备"));
            subTasks.add(createSubTask("填写产品申请表", 2, "去填写"));
        } else if ("2".equals(progressCode)) {
            // 提交用印阶段
            subTasks.add(createSubTask("录入临柜经办人", 2, "去录入"));
            subTasks.add(createSubTask("资料准备及进度", 2, "3/15"));
            subTasks.add(createSubTask("提交用印", 2, "去提交"));
        } else if ("3".equals(progressCode)) {
            // 递交机构阶段
            subTasks.add(createSubTask("准备托管协议", 1, "已完成"));
            subTasks.add(createSubTask("银行审批跟踪", 2, "去跟踪"));
        } else if ("4".equals(progressCode)) {
            // 账户回执报备阶段
            subTasks.add(createSubTask("接收账户回执", 1, "已完成"));
            subTasks.add(createSubTask("信息录入系统", 2, "去录入"));
            subTasks.add(createSubTask("文件归档", 2, "去归档"));
        }

        return subTasks;
    }

    /**
     * 创建子任务
     */
    private SubTaskVO createSubTask(String name, Integer status, String statusText) {
        SubTaskVO subTask = new SubTaskVO();
        subTask.setName(name);
        subTask.setTaskName(name);
        subTask.setStatus(status);
        subTask.setStatusText(statusText);
        subTask.setStatusName(status == 1 ? "已完成" : "待处理");
        return subTask;
    }

    /**
     * 获取账户类型名称
     */
    private String getAcctTypeName(String acctType) {
        if (acctType == null) {
            return "基金直销户";
        }
        // TODO: 从字典表查询
        switch (acctType) {
            case "1":
                return "托管账户";
            case "2":
                return "证券账户(深市A股)";
            case "3":
                return "证券账户(沪市B股)";
            case "4":
                return "证券资金账户";
            default:
                return "基金直销户";
        }
    }

    /**
     * 获取状态文本
     */
    private String getStatusText(String progressCode, Integer status) {
        if (status != null && status == 3) {
            return "已拒绝";
        }
        if (progressCode == null) {
            return "准备中";
        }
        switch (progressCode) {
            case "1":
                return "准备中";
            case "2":
                return "审核中";
            case "3":
                return "处理中";
            case "4":
                return "已完成";
            default:
                return "准备中";
        }
    }
}